/*
 * Copyright © 2004-2014 chenYuan. All rights reserved.
 * @Website:wwww.jspx.net
 * @Mail:39793751@qq.com
 * @author: chenYuan , 陈原
 * @License: Jspx.net Framework Code is open source (LGPL)，Jspx.net Framework 使用LGPL 开源授权协议发布。
 * @jvm:jdk1.6+  x86/amd64
 *
 */
package com.jspx.util;

import com.jspx.boot.environment.Environment;
import com.jspx.io.*;
import com.jspx.utils.*;
import java.io.*;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User:chenYuan (mail:39793751@qq.com)
 * Date: 2006-6-18
 * Time: 13:58:30
 * 内存映射表
 * 保存格式
 * [:-br]
 */

public class StringMap extends LinkedHashMap<String, String> implements Serializable {
    final private String[] keySplits = new String[]{StringUtil.COMMAS,StringUtil.EQUAL,StringUtil.COLON};
    final private String[] lineSplits = new String[]{StringUtil.SEMICOLON,StringUtil.CRLF};

    private String keySplit = StringUtil.COLON;
    private String lineSplit = StringUtil.CRLF;
    private String encode = Environment.defaultEncode;
    private boolean filter = false;
    private boolean split = false;
    private boolean security = false;

    public boolean isSecurity() {
        return security;
    }

    public void setSecurity(boolean security) {
        this.security = security;
    }

    public boolean isFilter() {
        return filter;
    }

    public void setFilter(boolean filter) {
        this.filter = filter;
    }

    public String getEncode() {
        return encode;
    }

    public void setEncode(String encode) {
        this.encode = encode;
    }

    public String getKeySplit() {
        return keySplit;
    }

    public void setKeySplit(String keySplit) {
        this.keySplit = keySplit;
        split = true;
    }

    public boolean isSplit() {
        return split;
    }

    public void setSplit(boolean split) {
        this.split = split;
    }

    public String getLineSplit() {
        return lineSplit;
    }

    public void setLineSplit(String lineSplit) {
        this.lineSplit = lineSplit;
        split = true;
    }

    public StringMap() {
        super();
    }

    public StringMap(String text) {
        super();
        setString(text);
    }

    public void setMap(Map<String, String> map) {
        putAll(map);
    }

    public String getFileName() {
        return fileName;
    }

    public void loadFile(String fileName) throws Exception {
        loadFile(fileName, null);
    }

    public void loadFile(String fileName, String encode) throws Exception {
        this.fileName = fileName;
        this.encode = encode;
        clear();
        AbstractRead ar = null;
        if (security)
        {
            ar = new SecurityReadFile();
        } else {
            ar = new AutoReadTextFile();
        }
        ar.setFile(fileName);
        if (!StringUtil.isNULL(this.encode)) ar.setEncode(this.encode);
        setString(ar.getContent());
    }

    public String getString(String key, String defValue) {
        String o = super.get(key);
        if (!StringUtil.isNULL(o)) return o;
        return defValue;
    }

    public String getString(String key)
    {
        String o = super.get(key);
        if (!StringUtil.isNULL(o)) return o;
        return StringUtil.empty;
    }

    public boolean getBoolean(String key) {
        return ObjectUtil.toBoolean(super.get(key));
    }

    public int getInt(String key) {
        return ObjectUtil.toInt(super.get(key));
    }

    public long getLong(String key) {
        return ObjectUtil.toInt(super.get(key));
    }

    public int getInt(String key,int def) {
        if (!super.containsKey(key)) return def;
        return ObjectUtil.toInt(super.get(key));
    }

    public Object removeFirst()
    {
        Object obj = null;
        Iterator<String> it = keySet().iterator();
        if (it.hasNext()) {
            String v = it.next();
                obj = super.get(v);
                it.remove();
        }
        return obj;

    }

    public Object remove(String key)
    {
        Object obj = null;
        Iterator<String> it = keySet().iterator();
        while (it.hasNext()) {
            String v = it.next();
            if (v.equals(key))
            {
                obj = super.get(v);
                it.remove();
            }
        }
        return obj;
    }

    public Object removeLast()
    {
        String lastKey = null;
        Iterator<String> it = keySet().iterator();
        while (it.hasNext()) {
            lastKey = it.next();
        }
        return remove(lastKey);
    }

    /**
     *
     * LRU 方式删除，会保留最新的 size 个
     * @param size  保留数
     * @return  删除并保留一定长度
     */
    public void removeLRU(int size)
    {
        Iterator<String> it = keySet().iterator();
        while (it.hasNext()&&super.size()>size) {
            it.next();
            it.remove();
        }
    }

    public String put(String key, String value) {
        remove(key);
        return super.put(key, value);
    }


    private String fileName;
    public boolean save() {
        return save(fileName, encode);
    }
    public boolean save(String fileName)
    {
        return save(fileName, encode);
    }
    public boolean save(String fileName, String encode)
    {
        AbstractWrite aw = null;
        if (security)
        {
            aw = new SecurityWriteFile();
        } else {
            aw = new WriteFile();
        }
        aw.setFile(fileName);
        if (!StringUtil.isNULL(encode)) aw.setEncode(encode);
        return aw.setContent(toString(), false);
    }

    public void setString(String text) {
        clear();
        if (text == null) return;
        if (!split)
        {
            int[] chkArray = ArrayUtil.getInitedIntArray(keySplits.length,0);
            for (int i=0;i<keySplits.length;i++)
            {
                chkArray[i] = StringUtil.countMatches(text,keySplits[i]);
            }
            int maxIndex = ArrayUtil.maxIndex(chkArray);
            keySplit = keySplits[maxIndex];

            int[] chkLineArray = ArrayUtil.getInitedIntArray(lineSplits.length,0);
            for (int i=0;i<lineSplits.length;i++)
            {
                chkLineArray[i] = StringUtil.countMatches(text,lineSplits[i]);
            }
            int maxLineIndex = ArrayUtil.maxIndex(chkLineArray);
            lineSplit = lineSplits[maxLineIndex];
        }


        String[] textArray = StringUtil.split(text, lineSplit);
        if (textArray.length > 0)
        {
            for (String str : textArray) {
                if (str.startsWith("#")) {
                    continue;
                }
                if (!filter && !str.contains(keySplit)) {
                    put(str, str);
                } else if (filter && !str.contains(keySplit)) {
                    //..
                } else {
                    String keys = StringUtil.substringBefore(str, keySplit);
                    if (keys.contains("/~")) StringUtil.replace(keys,  "/~",keySplit);
                    String value = StringUtil.trim(StringUtil.substringAfter(str, keySplit));
                    if (StringUtil.hasLength(keys)) put(keys, value);
                }
            }
        }
    }


    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (String key : keySet()) {
            if (key != null) {
                sb.append(StringUtil.replace(key, keySplit, "/~")).append(keySplit).append(ObjectUtil.toString(get(key)));
                sb.append(lineSplit);
            }
        }
        return sb.toString();
    }

    public Map<String,Object> getValueMap()
    {
        Map<String,Object> vMap =  new HashMap<String, Object>();
        for (String key:super.keySet())
        {
            vMap.put(key,super.get(key));
        }
        return vMap;
    }

    public List<String> getSortByKey()
    {
        List<String> keyList = new ArrayList<String>();
        keyList.addAll(super.keySet());
        Collections.sort(keyList);
        return keyList;
    }


    public void sortByKey(boolean delNull)
    {
        Map<String,String> vMap =  new LinkedHashMap<String, String>();
        List<String> keyList = getSortByKey();
        for (String key:keyList)
        {
            Object obj = super.get(key);
            if (delNull&&obj==null) continue;
            if (ClassUtil.isNumberType(obj.getClass()))
                vMap.put(key,ObjectUtil.toString(obj));
            else
                vMap.put(key,obj.toString());
        }
        super.clear();
        super.putAll(vMap);
    }


}